﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

using gma.System.Windows;

using PresentationUtils;
using LoggerUtils;
using System.IO;

namespace CrèchePager
{
    public partial class frmMain : Form
    {
        private frmNotices noticesForm = new frmNotices();

        private List<ScreenListItem> someScreens = new List<ScreenListItem>();
        private List<Notice> notices = new List<Notice>();

        public frmMain()
        {
            InitializeComponent();

            SetupNoticeModule();

            SetupPresentationModule();
        }

        private void SetupNoticeModule()
        {
            int i = 0;
            Screen screenToUse = Utils.FindScreenToUse();
            int screenToSelect = -1;
            foreach (Screen screen in Screen.AllScreens)
            {
                someScreens.Add(new ScreenListItem(string.Format("Screen {0} {1}", i, screen.Primary ? "[P]" : ""), screen));
                if (screen == screenToUse)
                {
                    screenToSelect = i;
                }
                i++;
            }

            lstMonitors.DataSource = someScreens;
            lstMonitors.DisplayMember = "Name";
            lstMonitors.SelectedIndex = screenToSelect;
        }

        private void btAdd_Click(object sender, EventArgs e)
        {
            if (tbNumber.Text != "")
            {
                string message = string.Format("{0} {1}", GetGroupName(), tbNumber.Text);
                AddNotice(message);
            }
        }

        private void AddNotice(string message)
        {
            notices.Add(new Notice(message));
            RebindLists();

            if (!noticesForm.Visible)
            {
                noticesForm.Show(this);
            }
            this.Focus();
        }

        private void RebindLists()
        {
            lstNotices.DataSource = null;
            lstNotices.DataSource = notices;

            noticesForm.Notices.DataSource = null;
            noticesForm.Notices.DataSource = notices;
        }

        private void btEnd_Click(object sender, EventArgs e)
        {
            List<Notice> toRemove = new List<Notice>();
            foreach (Notice n in lstNotices.SelectedItems)
            {
                toRemove.Add(n);
            }
            foreach (Notice n in toRemove)
            {
                notices.Remove(n);
            }
            if (lstNotices.Items.Count == 0)
            {
                noticesForm.Hide();
            }
            RebindLists();
        }

        private void btAddFreeText_Click(object sender, EventArgs e)
        {
            AddNotice(tbFreeText.Text);
        }

        private void lstMonitors_SelectedIndexChanged(object sender, EventArgs e)
        {
            noticesForm.ScreenToUse = ((ScreenListItem)lstMonitors.SelectedItem).TheScreen;
        }

        private string GetGroupName()
        {
            if (rbWhite.Checked)
                return "Wit";
            else if (rbYellow.Checked)
                return "Geel";
            else if (rbRed.Checked)
                return "Rood";
            else if (rbOrange.Checked)
                return "Oranje";
            throw new Exception("No color selected");
        }

        #region Presentation fields

        Presentation presentation;

        UserActivityHook actHook;

        #endregion

        #region Presentation events

        private void btBrowse_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                txtFile.Text = openFileDialog.FileName;
            }
        }

        private void btOpen_Click(object sender, EventArgs e)
        {
            OpenPresentation();
        }

        private void btClose_Click(object sender, EventArgs e)
        {
            ClosePresentation();
        }

        private void nudSlideNumber_ValueChanged(object sender, EventArgs e)
        {
            presentation.GoTo((int)nudSlideNumber.Value);
        }

        private void btFirst_Click(object sender, EventArgs e)
        {
            Logger.log("Goto first slide");

            presentation.First();
        }

        private void btLast_Click(object sender, EventArgs e)
        {
            Logger.log("Goto last slide");

            presentation.Last();
        }

        private void btPrevious_Click(object sender, EventArgs e)
        {
            Logger.log("Goto previous slide");
            presentation.Previous();
        }

        private void btNext_Click(object sender, EventArgs e)
        {
            Logger.log("Goto next slide");
            presentation.Next();
        }

        private void lstSlides_SelectedIndexChanged(object sender, EventArgs e)
        {
            presentation.GoTo(lstSlides.SelectedIndex + 1);
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            if (presentation == null)
                return;

            try
            {
                int nr = presentation.CurrentSlideNumber;

                nudSlideNumber.Value = nr;
                lstSlides.SelectedIndex = nr - 1;
            }
            catch (Exception) { }
        }

        #endregion

        #region Presentation helpers

        private void SetupPresentationModule()
        {
            disableNavigation();
            enableOpen();
        }

        private void OpenPresentation()
        {
            if (!File.Exists(txtFile.Text))
            {
                string msg = "File not found: " + txtFile.Text;
                Logger.log(msg);
                MessageBox.Show(msg);
                return;
            }

            Logger.log("Start presentation: " + txtFile.Text);
            presentation = new Presentation(txtFile.Text);
            presentation.PresentationEnd += presentation_PresentationEnd;

            enableNavigation();
            enableClose();

            TopMost = true;
            timer.Enabled = true;
        }

        private void ClosePresentation()
        {
            timer.Enabled = false;

            Logger.log("Close presentation");

            disableNavigation();

            presentation.ClosePresentation();
            presentation = null;
            enableOpen();
        }

        void presentation_PresentationEnd()
        {
            this.Invoke(new MethodInvoker(ClosePresentation));
        }

        private void enableOpen()
        {
            btClose.Enabled = false;
            btOpen.Enabled = true;
        }

        private void enableClose()
        {
            btClose.Enabled = true;
            btOpen.Enabled = false;
        }

        private void enableNavigation()
        {
            btFirst.Enabled = true;
            btLast.Enabled = true;
            btNext.Enabled = true;
            btPrevious.Enabled = true;
            nudSlideNumber.Enabled = true;

            nudSlideNumber.Minimum = 1;
            nudSlideNumber.Maximum = presentation.NumberOfSlides + 1;
            lstSlides.Items.AddRange(presentation.SlideNames);
            lstSlides.Items.Add("End-page");

            // TODO: Re-enable this
            actHook = new UserActivityHook(false, true); // create an instance with global hooks
            // hook on events
            actHook.KeyDown += MyKeyDown;
        }

        private void disableNavigation()
        {
            if (actHook != null)
            {
                actHook.KeyDown -= MyKeyDown;
                actHook.Stop();
            }

            btFirst.Enabled = false;
            btLast.Enabled = false;
            btNext.Enabled = false;
            btPrevious.Enabled = false;
            nudSlideNumber.Enabled = false;

            lstSlides.Items.Clear();
        }

        public delegate void Decouple(KeyEventArgs e);

        public void MyKeyDown(object sender, KeyEventArgs e)
        {
            if (presentation == null)
                return;

            // TODO: decouple the events as we are not allowed to use them synchronously
            Logger.log(String.Format("Key {0}", e.KeyCode));
            Decouple decouple = new Decouple(OnDecouple);
            decouple.BeginInvoke(e, null, null);
        }

        public void OnDecouple(KeyEventArgs e)
        {
            Logger.log(String.Format("Key picked up {0}", e.KeyCode));
            if (e.KeyCode == Keys.PageDown)
            {
                presentation.Next();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.PageUp)
            {
                presentation.Previous();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.Home)
            {
                presentation.First();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.End)
            {
                presentation.Last();
                e.Handled = true;
            }
        }

        #endregion
    }
}
